diff options
| author | real-zephex <[email protected]> | 2024-03-25 11:33:09 +0530 |
|---|---|---|
| committer | real-zephex <[email protected]> | 2024-03-25 11:33:09 +0530 |
| commit | 9202a2b6790e57dc35d0563d014e89d981a65e37 (patch) | |
| tree | f2258b96400d6df9753c2c52531ba7f8897b9fa3 /src/app/manga/[title] | |
| parent | fix: requests are revalidated after 30 mins. this prevents stale data from be... (diff) | |
| download | dramalama-9202a2b6790e57dc35d0563d014e89d981a65e37.tar.xz dramalama-9202a2b6790e57dc35d0563d014e89d981a65e37.zip | |
feature added: mangas are now available
Diffstat (limited to 'src/app/manga/[title]')
| -rw-r--r-- | src/app/manga/[title]/[id]/[read]/page.jsx | 51 | ||||
| -rw-r--r-- | src/app/manga/[title]/[id]/[read]/read.module.css | 43 | ||||
| -rw-r--r-- | src/app/manga/[title]/[id]/buttons.jsx | 28 | ||||
| -rw-r--r-- | src/app/manga/[title]/[id]/info.module.css | 135 | ||||
| -rw-r--r-- | src/app/manga/[title]/[id]/page.jsx | 102 | ||||
| -rw-r--r-- | src/app/manga/[title]/page.jsx | 74 | ||||
| -rw-r--r-- | src/app/manga/[title]/title.module.css | 61 |
7 files changed, 494 insertions, 0 deletions
diff --git a/src/app/manga/[title]/[id]/[read]/page.jsx b/src/app/manga/[title]/[id]/[read]/page.jsx new file mode 100644 index 0000000..a90d170 --- /dev/null +++ b/src/app/manga/[title]/[id]/[read]/page.jsx @@ -0,0 +1,51 @@ +import styles from "./read.module.css"; +import Image from "next/image"; + +export default async function Read({ params }) { + const chapterId = params.read; + const data = await getPages(chapterId); + if (data.length === 0) { + return ( + <div className={styles.NotFound}> + <p> + This chapter has no content. Please check the next chapter. + </p> + </div> + ); + } + + let images = []; + for (var i = 0; i < data.length; i++) { + var imgUrl = data[i].img; + images.push(imgUrl); + } + + return ( + <div className={styles.Main}> + <div className={styles.ImageContainer}> + {images && + images.map((item, index) => ( + <div className={styles.Image}> + <Image + src={`https://image-proxy-manga.vercel.app/image-proxy?url=${item}`} + key={index} + alt="Pages" + width={800} + height={1000} + priority + /> + <p>{index + 1}</p> + </div> + ))} + </div> + </div> + ); +} + +async function getPages(id) { + const res = await fetch( + `https://consumet-api-di2e.onrender.com/meta/anilist-manga/read?chapterId=${id}&provider=mangadex` + ); + const data = await res.json(); + return data; +} diff --git a/src/app/manga/[title]/[id]/[read]/read.module.css b/src/app/manga/[title]/[id]/[read]/read.module.css new file mode 100644 index 0000000..3a8c99f --- /dev/null +++ b/src/app/manga/[title]/[id]/[read]/read.module.css @@ -0,0 +1,43 @@ +.ImageContainer img { + width: auto; + height: auto; + border-radius: 5px; + margin-top: 10px; + +} + +.Image { + display: flex; + flex-direction: column; + align-items: center; + background-color: #1b1b1b; + border-radius: 10px; + width: auto; + margin-top: 10px; +} + +.ImageContainer p { + text-align: center; + color: white; + font-family: "Kanit"; + font-size: 16px; + margin: 5px; +} + +.NotFound { + text-align: center; + color: white; + font-family: "Atkinson Hyperlegible"; + font-size: 20px; +} + +@media screen and (max-width: 768px) { + .ImageContainer img { + width: 90%; + align-items: center; + } + + .Image { + width: 100%; + } +}
\ No newline at end of file diff --git a/src/app/manga/[title]/[id]/buttons.jsx b/src/app/manga/[title]/[id]/buttons.jsx new file mode 100644 index 0000000..07fe3c3 --- /dev/null +++ b/src/app/manga/[title]/[id]/buttons.jsx @@ -0,0 +1,28 @@ +import styles from "./info.module.css"; +import Link from "next/link"; + +export default async function Buttons({ content: data }) { + return ( + <div className={styles.ChapterContainer}> + {data.chapters && + data.chapters.map((item, index) => { + if (item.pages !== 0) { + return ( + <Link + href={{ + pathname: `/manga/info/read/${item.id}`, + query: { + name: item.title, + }, + }} + > + <button key={index}> + {item.volumeNumber} - {item.chapterNumber} + </button> + </Link> + ); + } + })} + </div> + ); +} diff --git a/src/app/manga/[title]/[id]/info.module.css b/src/app/manga/[title]/[id]/info.module.css new file mode 100644 index 0000000..99ea636 --- /dev/null +++ b/src/app/manga/[title]/[id]/info.module.css @@ -0,0 +1,135 @@ +.MangaInfoContainer { + max-width: 90%; + margin: 0px auto; +} + +.MangaHero { + display: flex; + flex-direction: column; +} + +.HeroImage { + width: 100%; + height: auto; + max-height: 550px; + border-radius: 10px; +} + +.TitleContainer { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 10px; +} + +.TitleContainer p { + font-family: "Lato"; + font-size: 32px; +} + +.TitleContainer img { + border-radius: 10px; +} + +.MangaDescription { + color: white; + font-family: "Atkinson Hyperlegible"; + text-align: center; +} + +.MangaDescription span { + margin: 10px; + color: var(--soft-purple); +} + +.MangaRatings { + color: var(--light-green); +} + +.MangaGenre { + background-color: #5f5f5f5d; + padding: 2px; + border-radius: 5px; + cursor: pointer; +} + +.Character { + display: flex; + flex-direction: row; + overflow-x: auto; +} + +.Character::-webkit-scrollbar { + height: 5px; +} + +.Character::-webkit-scrollbar-thumb { + background-color: #949494; + border-radius: 5px; +} + +.Character::-webkit-scrollbar-track { + background-color: rgb(87, 87, 87); + border-radius: 5px; +} + +.CharacterEntry { + margin: 5px; +} + +.CharacterEntry p { + text-align: center; + color: white; +} + +.CharacterEntry img { + border-radius: 10px; +} + +/* Chapters Buttons */ +.ChapterContainer { + width: 95%; + margin: 20px auto; + text-align: center; + height: 400px; + overflow-y: auto; +} + +.ChapterContainer::-webkit-scrollbar { + width: 5px; +} + +.ChapterContainer::-webkit-scrollbar-thumb { + background-color: #949494; + border-radius: 5px; +} + +.ChapterContainer::-webkit-scrollbar-track { + background-color: rgb(66, 66, 66); + border-radius: 5px; +} + +.ChapterContainer button { + width: 100px; + padding: 10px; + margin: 5px; + border-radius: 5px; + font-size: 16px; + border: none; + outline: none; + font-family: "Lato"; + background-color: #41C9E2; + cursor: pointer; + transition: transform 0.2s linear; + +} + +.ChapterContainer button:hover { + background-color: var(--neon-green); +} + +.ChapterContainer button:focus { + opacity: 0.6; + transition: transform 0.2s linear; + transform: scale(0.9); +}
\ No newline at end of file diff --git a/src/app/manga/[title]/[id]/page.jsx b/src/app/manga/[title]/[id]/page.jsx new file mode 100644 index 0000000..b41f719 --- /dev/null +++ b/src/app/manga/[title]/[id]/page.jsx @@ -0,0 +1,102 @@ +import styles from "./info.module.css"; +import Image from "next/image"; +import Buttons from "./buttons"; + +export default async function MangaInfo({ params }) { + const id = params.id; + const data = await getMangaInfo(id); + + return ( + <div className={styles.MangaInfoContainer}> + {data && ( + <div className={styles.MangaInfo}> + <div className={styles.MangaHero}> + <Image + src={data.cover} + width={1730} + height={400} + alt="Cover Poster" + className={styles.HeroImage} + priority + /> + <div className={styles.TitleContainer}> + <p style={{ color: data.color }}> + {data.title["romaji"]} + </p> + <Image + src={data.image} + width={200} + height={310} + alt="Manga Poster" + priority + /> + </div> + </div> + + <div className={styles.MangaDescription}> + <p>{data.description.split("<br")[0]}</p> + <span className={styles.MangaReleaseYear}> + Released in: {data.releaseDate} + </span> + <span> + Started on: {data.startDate["day"]}- + {data.startDate["month"]}-{data.startDate["year"]} + </span> + <span> + Ended on: {data.endDate["day"]}- + {data.endDate["month"]}-{data.endDate["year"]} + </span> + <p className={styles.MangaRatings}> + Ratings: {data.rating / 10} + </p> + <p style={{ color: "#7ED7C1" }}> + Genres: + {data.genres && + data.genres.map((item, index) => ( + <span + key={index} + className={styles.MangaGenre} + style={{ color: data.color, margin: 5 }} + > + {item} + </span> + ))} + </p> + </div> + + <div className={styles.CharactersContainer}> + <div className={styles.Character}> + {data.characters && + data.characters.map((item, index) => ( + <div + key={index} + className={styles.CharacterEntry} + > + <Image + src={item.image} + width={140} + height={200} + alt="Character Poster" + /> + <p> + {item.name.full} ({item.role}) + </p> + </div> + ))} + </div> + </div> + + <Buttons content={data} /> + </div> + )} + </div> + ); +} + +async function getMangaInfo(id) { + const res = await fetch( + `https://consumet-api-di2e.onrender.com/meta/anilist-manga/info/${id}?provider=mangadex` + ); + const data = await res.json(); + return data; +} diff --git a/src/app/manga/[title]/page.jsx b/src/app/manga/[title]/page.jsx new file mode 100644 index 0000000..92c2897 --- /dev/null +++ b/src/app/manga/[title]/page.jsx @@ -0,0 +1,74 @@ +import styles from "./title.module.css"; +import Image from "next/image"; +import Link from "next/link"; + +export default async function MangaInfo({ params }) { + const title = params.title; + const data = await GetSearchedAnime(title); + + return ( + <div className={styles.Main}> + <div className={styles.MangaContainer}> + {title && ( + <div className={styles.SearchedFor}> + <p>Searched for: {decodeURIComponent(title)}</p> + </div> + )} + {data && + data.results.map(async (item, index) => { + let desc = item.description || ""; // Ensure desc is not null + if (desc === "") { + desc = "Not found"; // If desc is empty, set it to "Not found" + } + return ( + <Link + href={`./info/${item.id}`} + style={{ textDecoration: "none" }} + key={index} + > + <div className={styles.MangaEntries}> + <Image + src={item.image} + width={140} + height={240} + alt="Manga Poster" + style={{ borderRadius: 10 }} + /> + <div className={styles.MangaInfo}> + <p className={styles.MangaTitle}> + {item.title["romaji"]},{" "} + {item.title["english"]},{" "} + {item.title["native"]} + </p> + <p className={styles.MangaDescription}> + {desc.includes && + desc.includes("<br") + ? desc.split("<b")[0] + : desc} + </p> + <p className={styles.MangaStatus}> + {item.status} + </p> + <p className={styles.MangaChapters}> + Chapters: {item.totalChapters} + </p> + <p className={styles.MangaVolume}> + Volumes: {item.volumes} + </p> + </div> + </div> + </Link> + ); + })} + </div> + </div> + ); +} + +async function GetSearchedAnime(title) { + const res = await fetch( + "https://consumet-api-di2e.onrender.com/meta/anilist-manga/" + title + ); + const data = await res.json(); + return data; +} diff --git a/src/app/manga/[title]/title.module.css b/src/app/manga/[title]/title.module.css new file mode 100644 index 0000000..eef08ba --- /dev/null +++ b/src/app/manga/[title]/title.module.css @@ -0,0 +1,61 @@ +.Main { + max-width: 90%; + margin: 0px auto; +} + +.MangaContainer { + display: flex; + flex-direction: column; +} + +.SearchedFor { + color: white; + text-align: center; + font-family: "Kanit"; + font-size: 26px; +} + +.MangaEntries { + display: flex; + flex-direction: row; + margin: 10px; + padding: 10px; + border-style: dotted; + border-color: #363636 #474747; + border-radius: 10px; + border-width: 4px; + align-items: center; + cursor: pointer; + transition: transform 0.2s linear; +} + +.MangaEntries:hover { + transition: transform 0.2s linear; + transform: scale(1.01); + border-color: #535353 #686868; + +} + +.MangaInfo { + color: white; + margin-left: 20px; +} + +.MangaTitle { + font-family: "Lato"; + margin: 0px; + font-size: 22px; + color: var(--neon-green); +} + +.MangaStatus { + color: var(--soft-purple); +} + +.MangaVolume { + color: #FFACAC; +} + +.MangaChapters { + color: #FFEBB4 +}
\ No newline at end of file |